package org.jside.cdn;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;

import org.xidea.jsi.JSIPackage;
import org.xidea.jsi.ScriptNotFoundException;
import org.xidea.jsi.web.JSIFilter;

/**
 * JSICDN,通过URL 按需装载脚本庄1�7
 * path:/scripts/;org.jside:Tween+org.jside:format+org.xidea.test.*
 * 
 * @author jindw
 */
public class CDNServlet extends JSIFilter {
	private static final int VALID_TIME = 1000*60*60;
	public static final String CDN_DEBUG_TOKEN_NAME = "CDN_DEBUG";
	static CDNServlet instance;
	private Map<String, String> cachedMap = new WeakHashMap<String, String>();
	private String list = "/cdn-list.xhtml";
	private JSIScriptExportor exportor;
	{
		instance = this;
		this.scriptBase = "/cdn/";
	}

	@Override
	public void service(ServletRequest req, ServletResponse resp)
			throws ServletException, IOException {
		resp.setCharacterEncoding("utf-8");
		try {
			super.service(req, resp);
		} catch (ScriptNotFoundException e) {
			//HttpServletResponse response = (HttpServletResponse) resp;
			RequestDispatcher dispatcher = context.getRequestDispatcher(list);
			req.setAttribute("error", e.getMessage());
			List<JSIPackage> pl = new ArrayList<JSIPackage>();
			for(JSIPackage p :this.getPackageObjectList()){
				Set<String> keys = p.getScriptObjectMap().keySet();
				if(keys.isEmpty() || keys.iterator().next().toLowerCase().endsWith(".js")){
					pl.add(p);
				}
			}
			
			req.setAttribute("packageList", pl);
			dispatcher.forward(req, resp);
		}
	}

	protected boolean processAttachedAction(HttpServletRequest request,
			HttpServletResponse response, String path) throws IOException {
		if (path.startsWith("=")) {
			path = path.substring(1);
			if(path.length()==0){
				throw new ScriptNotFoundException("");
			}
			String[] paths = JSIScriptExportor.CDN_PATH_SPLITER
					.split(path);
			// TODO:以后应该使用Stream，应该使用成熟的缓存系统
			PrintWriter out = response.getWriter();
			response.setContentType("text/plain;charset=utf-8");
			String result;
			if (isDebug(request)) {
				result = exportor.doDebugExport(paths);
			} else if("POST".equals(request.getMethod())){
				result = exportor.queryExportInfo(path);
			} else {
				result = cachedMap.get(path);
				if(result == null){
					result = exportor.doReleaseExport(paths);
					cachedMap.put(path,result);
				}
			}
			// 应该考虑加上字节流缓孄1�7
			out.append(result);
			out.flush();
			return true;
		} else {
			return super.processAttachedAction(path,request, response);
		}
	}
	public String queryExportInfo(String path){
		return exportor.queryExportInfo(path);
	}

	public static String getDebugTokenValue(ServletContext context) {
		String token = (String) context.getAttribute(CDN_DEBUG_TOKEN_NAME);
		long time = System.currentTimeMillis();
		String prefix = Long.toString(time / VALID_TIME,32);
		if(token == null || !token.startsWith(prefix)){
			token = prefix + (int)(100*Math.random());
			context.setAttribute(CDN_DEBUG_TOKEN_NAME, token);
		}
		return token;
	}

	public boolean isDebug(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (CDN_DEBUG_TOKEN_NAME.equals(cookie.getName())) {
					return getDebugTokenValue(context).equals(cookie.getValue());
				}
			}
		}
		return false;
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		this.exportor = new JSIScriptExportor(this);
	}
}
